package com.ds.infrastructure.hyperspace.common;

import com.ds.infrastructure.hyperspace.common.config.TargetNodeConfig;
import com.ds.infrastructure.hyperspace.common.flow.DuplexFlowContext;

/**
 * Note: the class not allow thread switch
 * @author  Weishaoying
 */
public interface TargetEndpointStream {

    /**
     * Get target endpoint node
     * @return
     */
    EndpointNode<TargetNodeConfig> getTargetEndpointNode();

    /**
     * Connect to target node
     */
    void connect();

    /**
     * Get stream status
     * @return
     */
    TargetEndpointStreamStatus getStatus();

    /**
     * Forward request to channel stream
     * @param duplexFlowContext
     * @param data
     * @param <C>
     */
    <C extends DuplexFlowContext> void handleInput(C duplexFlowContext, Object data);

    /**
     * handle request last packet
     * @param duplexFlowContext
     * @param <C>
     */
    <C extends DuplexFlowContext> void handleInputComplete(C duplexFlowContext);

    /**
     * Fire while target channel close
     * @return
     */
    void onTargetChannelClose();

    /**
     * Set channel readable
     * @param readable
     */
    void changeTargetChannelReadable(boolean readable);

    /**
     * Close target channel
     */
    void closeTargetChannel();

    /**
     * Switch to another protocol
     * @param duplexFlowContext
     * @param protocol
     */
    <C extends DuplexFlowContext> void switchProtocol(C duplexFlowContext,
            EndpointProtocolEnum protocol);

    /**
     * Is available target node
     * @return
     */
    boolean isAvailableTargetNode();

    /**
     * Clear suspend request in node stream
     */
    void clearSuspendRequest();

    /**
     * Notice when entry channel closed
     */
    void noticeEntryChannelClosed();
}
